Xceed DataGrid for WPF v7.3 Documentation
Welcome to Xceed DataGrid, Editors, and 3D Views for WPF v7.3 / Xceed DataGrid for WPF / Code Snippets / Using Statistical Functions

In This Topic
    Using Statistical Functions
    In This Topic

    The following page provides a list of examples that demonstrate how to validate data. For more data statistic-related information, refer to the Statistical Functions topic.

    All examples in this topic assume that the grid is bound to the OrderDetails table of the Northwind database, unless stated otherwise.


    Displaying statistical functions

    The following example demonstrates how to display the results of various statistical functions in and outside of a grid.

    XAML
    Copy Code
    <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
      <Grid.Resources>
        <xcdg:DataGridCollectionViewSource x:Key="cvs_orderdetails"
                                           Source="{Binding Source={x:Static Application.Current},
                                                            Path=OrderDetails}">
         <xcdg:DataGridCollectionViewSource.StatFunctions>
           <xcdg:CountFunction ResultPropertyName="orderid_count"
                               SourcePropertyName="OrderID"/>
           <xcdg:SumFunction ResultPropertyName="unitprice_sum"
                             SourcePropertyName="UnitPrice"/>
           <xcdg:SumFunction ResultPropertyName="quantity_sum" SourcePropertyName="Quantity"/>
         </xcdg:DataGridCollectionViewSource.StatFunctions>
         <xcdg:DataGridCollectionViewSource.GroupDescriptions>
           <xcdg:DataGridGroupDescription PropertyName="ProductID"/>      
     </xcdg:DataGridCollectionViewSource.GroupDescriptions>
        </xcdg:DataGridCollectionViewSource>
       <xcdg:StatResultConverter x:Key="valueConverter"/>
      </Grid.Resources>
      <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
          <TextBlock Text="Total Orders: "/>
          <TextBlock Text="{Binding ElementName=OrderDetailsGrid,
                     Path=StatContext.orderid_count}"/>
        </StackPanel>
         <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
           <TextBlock Text="Average Unit Price: "/>
         <TextBlock Text="{Binding ElementName=OrderDetailsGrid,
                            Path=StatContext.unitprice_average,
                            Converter={StaticResource valueConverter},
                            ConverterParameter=f2}"/>
        </StackPanel>
        <xcdg:DataGridControl x:Name="OrderDetailsGrid"
                              ItemsSource="{Binding Source={StaticResource cvs_orderdetails}}"
                              DockPanel.Dock="Bottom">
          <xcdg:DataGridControl.DefaultGroupConfiguration>
            <xcdg:GroupConfiguration> 
            <xcdg:GroupConfiguration.Footers>
               <DataTemplate>
                   <xcdg:StatRow>
                   <xcdg:StatCell FieldName="UnitPrice"
                                  ResultPropertyName="unitprice_sum"/>
                   <xcdg:StatCell FieldName="Quantity"
                                  ResultPropertyName="quantity_sum"/>
                   <xcdg:StatCell FieldName="OrderID"
                                  ResultPropertyName="orderid_count"/>
                 </xcdg:StatRow>
               </DataTemplate>
             </xcdg:GroupConfiguration.Footers>
            </xcdg:GroupConfiguration>
          </xcdg:DataGridControl.DefaultGroupConfiguration>    
        </xcdg:DataGridControl>
      </DockPanel>
    </Grid>

    Changing statistical contexts

    The following example demonstrates how to change the statistical context of a TextBlock that displays the results of a statistical function when the current item is changed. The statistical context of the TextBlock will be changed in the grid's PropertyChanged event handler by using the GetParentGroupFromItem method to retrieve the current group and set it as the new statistical context.

    To simplify the code below, the DataContext of the StackPanel could have been modified rather than the DataContext of each TextBlock.

    The implementation of the PropertyChanged event handler is located below.

    XAML
    Copy Code
    <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
      <Grid.Resources>
        <xcdg:DataGridCollectionViewSource x:Key="cvs_orderdetails"
                                        Source="{Binding Source={x:Static Application.Current},
                                                         Path=OrderDetails}">
          <xcdg:DataGridCollectionViewSource.StatFunctions>
            <xcdg:CountFunction ResultPropertyName="orderid_count"
                                SourcePropertyName="OrderID"/>
            <xcdg:AverageFunction ResultPropertyName="unitprice_average"
                                  SourcePropertyName="UnitPrice"/>             
          </xcdg:DataGridCollectionViewSource.StatFunctions>
          <xcdg:DataGridCollectionViewSource.GroupDescriptions>
            <xcdg:DataGridGroupDescription PropertyName="ProductID"/>
          </xcdg:DataGridCollectionViewSource.GroupDescriptions>
        </xcdg:DataGridCollectionViewSource>
        <xcdg:StatResultConverter x:Key="valueConverter"/>
      </Grid.Resources>
      <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
          <TextBlock Text="Results for product "/>
          <TextBlock x:Name="CurrentGroupTitle" Text="{Binding Name}"/>
          <TextBlock Text=": "/>
          <TextBlock Text="     Total Orders-"/>
          <TextBlock x:Name="TotalOrders" Text="{Binding orderid_count}"/>
          <TextBlock Text="     Average Unit Price-"/>
          <TextBlock x:Name="AveragePrice"
                     Text="{Binding unitprice_average,
                            Converter={StaticResource valueConverter},
                            ConverterParameter=f2}"/>
        </StackPanel>
        <xcdg:DataGridControl x:Name="OrderDetailsGrid"
                              ItemsSource="{Binding Source={StaticResource cvs_orderdetails}}"
                              PropertyChanged="CurrentItemChanged"
                              DockPanel.Dock="Bottom"/>
      </DockPanel>
    </Grid>

    The following code provides the implementation of the PropertyChanged event handler.

    VB.NET
    Copy Code
    Private Sub CurrentItemChanged( ByVal sender As Object, _
                                    ByVal e AsPropertyChangedEventArgs  )
      If e.PropertyName = "CurrentItem" Then
        If Me.OrderDetailsGrid.CurrentItem Is Nothing Then
          Return
        End If
        Dim group As CollectionViewGroup =
                  Me.OrderDetailsGrid.GetParentGroupFromItem( Me.OrderDetailsGrid.CurrentItem )
        Me.CurrentGroupTitle.DataContext = group
        Me.TotalOrders.DataContext = group
        Me.AveragePrice.DataContext = group
      End If
    End Sub
    C#
    Copy Code
    private void CurrentItemChanged( object sender, PropertyChangedEventArgs e )
    {
      if( e.PropertyName == "CurrentItem" )
      {
        if( this.OrderDetailsGrid.CurrentItem == null )
          return;
        CollectionViewGroup group =
                  this.OrderDetailsGrid.GetParentGroupFromItem( this.OrderDetailsGrid.CurrentItem );
        this.CurrentGroupTitle.DataContext = group;
        this.TotalOrders.DataContext = group;
        this.AveragePrice.DataContext = group;
      }
    }

    Custom statistical-result layout

    The following example demonstrates how to create a custom data template that will be used in the footers of the first-level groups to display the results of various statistical functions.

    XAML
    Copy Code
    <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
      <Grid.Resources>
        <xcdg:DataGridCollectionViewSource x:Key="cvs_orderdetails"
                                           Source="{Binding Source={x:Static Application.Current},
                                                            Path=OrderDetails}"> 
        <xcdg:DataGridCollectionViewSource.StatFunctions>
           <xcdg:CountFunction ResultPropertyName="orderid_count"
                               SourcePropertyName="OrderID"/>
           <xcdg:SumFunction ResultPropertyName="unitprice_sum"
                             SourcePropertyName="UnitPrice"/>
           <xcdg:AverageFunction ResultPropertyName="unitprice_average"
                                 SourcePropertyName="UnitPrice"/>
           <xcdg:SumFunction ResultPropertyName="quantity_sum"
                             SourcePropertyName="Quantity"/>
         </xcdg:DataGridCollectionViewSource.StatFunctions>       
          <xcdg:DataGridCollectionViewSource.GroupDescriptions>
            <xcdg:DataGridGroupDescription PropertyName="ProductID"/>
          </xcdg:DataGridCollectionViewSource.GroupDescriptions>
        </xcdg:DataGridCollectionViewSource>
       <xcdg:StatResultConverter x:Key="valueConverter"/>
      </Grid.Resources>
      <xcdg:DataGridControl x:Name="OrderDetailsGrid"
                            ItemsSource="{Binding Source={StaticResource cvs_orderdetails}}">
        <xcdg:DataGridControl.DefaultGroupConfiguration>
          <xcdg:GroupConfiguration>
            <xcdg:GroupConfiguration.Footers>
              <xcdg:GroupHeaderFooterItemTemplate VisibleWhenCollapsed="True">
                <DataTemplate>
                  <Border Background="#999999"
                          BorderBrush="LightBlue"
                          BorderThickness="3"
                          Margin="5" >
                    <Grid>
                      <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                      </Grid.ColumnDefinitions>
                      <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                      </Grid.RowDefinitions>
                      <TextBlock Text="Total Orders: " Grid.Row="0" Grid.Column="0"/>
                       <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                                                 Path=(xcdg:DataGridControl.StatContext).orderid_count}"
                                  Grid.Row="0" Grid.Column="1"/>                    
                        <TextBlock Text="Total Quantity Sold: " Grid.Row="1" Grid.Column="0"/>
                       <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                                       Path=(xcdg:DataGridControl.StatContext).quantity_sum}"
                                       Grid.Row="1" Grid.Column="1"/>  
                        <TextBlock Text="Total Sales: " Grid.Row="2" Grid.Column="0"/>
                       <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                                                 Path=(xcdg:DataGridControl.StatContext).unitprice_sum}"
                                  Grid.Row="2" Grid.Column="1"/>  
                        <TextBlock Text="Average Unit Price: " Grid.Row="3" Grid.Column="0"/>
                       <TextBlock Text="{Binding RelativeSource={RelativeSource Self},
                                                 Path=(xcdg:DataGridControl.StatContext).unitprice_average,
                                                 Converter={StaticResource valueConverter},
                                                 ConverterParameter=f2}"
                                  Grid.Row="3" Grid.Column="1"/>         
                      </Grid>
                    </Border> 
                  </DataTemplate>  
                </xcdg:GroupHeaderFooterItemTemplate>
              </xcdg:GroupConfiguration.Footers>
            </xcdg:GroupConfiguration>
          </xcdg:DataGridControl.DefaultGroupConfiguration>
          <xcdg:DataGridControl.View>
            <xcdg:CardView AllowCardResize="True"/>
          </xcdg:DataGridControl.View>
        </xcdg:DataGridControl>
      </Grid>

    Displaying statistical functions in details

    The following example demonstrates how to explicitly define detail descriptions for the DataRelations found in the DataTable to which the grid is bound and how to calculate statistical functions for a detail description whose results will be displayed in the StatRows contained in the footer sections of the details to which the description's corresponding detail configuration will be applied.

    XAML
    Copy Code
    <Grid>
      <Grid.Resources>
         <xcdg:DataGridCollectionViewSource x:Key="cvs_employees"
                                            Source="{Binding Source={x:Static Application.Current},
                                                             Path=Employees}">
           <xcdg:DataGridCollectionViewSource.DetailDescriptions>
              <xcdg:DataRelationDetailDescription RelationName="Employee_Orders"
                                                  Title="Employee Orders">
                 <xcdg:DataRelationDetailDescription.DetailDescriptions>
                    <xcdg:DataRelationDetailDescription RelationName="Order_OrderDetails"
                                                        Title="Order Details">
                       <xcdg:DataRelationDetailDescription.ItemProperties>
                          <xcdg:DataGridItemProperty Name="UnitPrice" />
                          <xcdg:DataGridItemProperty Name="Quantity" />
                          <xcdg:DataGridItemProperty Name="Discount" />
                       </xcdg:DataRelationDetailDescription.ItemProperties>
                       <xcdg:DataRelationDetailDescription.StatFunctions>                         
                          <xcdg:SumFunction ResultPropertyName="sum_quantity"
                                            SourcePropertyName="Quantity" />
                          <xcdg:AverageFunction ResultPropertyName="average_unitprice"
                                                SourcePropertyName="UnitPrice" />
                       </xcdg:DataRelationDetailDescription.StatFunctions>
                    </xcdg:DataRelationDetailDescription>
                 </xcdg:DataRelationDetailDescription.DetailDescriptions>
              </xcdg:DataRelationDetailDescription>
           </xcdg:DataGridCollectionViewSource.DetailDescriptions>
         </xcdg:DataGridCollectionViewSource>
      </Grid.Resources>
     
      <xcdg:DataGridControl x:Name="EmployeesGrid"
                          ItemsSource="{Binding Source={StaticResource cvs_employees}}"
                          ItemsSourceName="Employee Information"
                          AutoCreateDetailConfigurations="True">
        <xcdg:DataGridControl.DetailConfigurations>
           <xcdg:DetailConfiguration RelationName="Employee_Orders">
              <xcdg:DetailConfiguration.DetailConfigurations>
                 <xcdg:DetailConfiguration RelationName="Order_OrderDetails">
                    <xcdg:DetailConfiguration.Footers>
                       <DataTemplate>
                          <xcdg:StatRow Background="AliceBlue">
                             <xcdg:StatCell FieldName="UnitPrice"
                                            ResultPropertyName="average_unitprice"
                                            ResultConverterParameter="f2" />
                             <xcdg:StatCell FieldName="Quantity"
                                            ResultPropertyName="sum_quantity" />                            
                          </xcdg:StatRow>
                       </DataTemplate>
                    </xcdg:DetailConfiguration.Footers>
                 </xcdg:DetailConfiguration>
              </xcdg:DetailConfiguration.DetailConfigurations>
           </xcdg:DetailConfiguration>
         </xcdg:DataGridControl.DetailConfigurations> 
       </xcdg:DataGridControl>
    </Grid>

    Custom statistical function

    The following example demonstrates how to create a custom statistical function based on the CountFunction, which will only count the items if they match the specified conditions.

    XAML
    Copy Code
    <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
          xmlns:local="clr-namespace:Xceed.Wpf.Documentation"
          xmlns:s="clr-namespace:System;assembly=mscorlib">
      <Grid.Resources>
         <xcdg:DataGridCollectionViewSource x:Key="cvs_products"
                                            Source="{Binding Source={x:Static Application.Current}, Path=Products}">
            <xcdg:DataGridCollectionViewSource.StatFunctions>
              <local:CountIfFunction ResultPropertyName="CountProductsToOrder"
                                     SourcePropertyName="ReorderLevel,UnitsOnOrder">
                 <!-- Only count products which have a ReorderLevel of 5, 10, 15, or 20, and
                      a UnitsOnOrder value of 0. -->
                 <local:CountIfFunction.Conditions>
                    <s:String>^5$|^10$|^15$|^20$</s:String>
                    <s:String>^0$</s:String>
                 </local:CountIfFunction.Conditions>
              </local:CountIfFunction>
            </xcdg:DataGridCollectionViewSource.StatFunctions>
            <xcdg:DataGridCollectionViewSource.GroupDescriptions>
               <xcdg:DataGridGroupDescription PropertyName="CategoryID" />
            </xcdg:DataGridCollectionViewSource.GroupDescriptions>
         </xcdg:DataGridCollectionViewSource>
      </Grid.Resources>
      <xcdg:DataGridControl x:Name="OrdersGrid"
                            ItemsSource="{Binding Source={StaticResource cvs_products}}">
         <xcdg:DataGridControl.Columns>
            <xcdg:Column FieldName="ReorderLevel"/>
         </xcdg:DataGridControl.Columns>
         <xcdg:DataGridControl.DefaultGroupConfiguration>
            <xcdg:GroupConfiguration>
               <xcdg:GroupConfiguration.Footers>
                  <DataTemplate>
                    <xcdg:StatRow Background="Pink">
                       <xcdg:StatCell FieldName="ReorderLevel"
                                      ResultPropertyName="CountProductsToOrder" />                      
                    </xcdg:StatRow>  
                </DataTemplate>
               </xcdg:GroupConfiguration.Footers>
            </xcdg:GroupConfiguration>
         </xcdg:DataGridControl.DefaultGroupConfiguration>
      </xcdg:DataGridControl>
    </Grid>
    VB.NET
    Copy Code
    Imports System
    Imports System.Collections.ObjectModel
    Imports System.Collections.Specialized
    Imports System.Text.RegularExpressions
    Imports Xceed.Wpf.DataGrid.Stats
    Namespace Xceed.Wpf.Documentation
      ' This statistical function derives from CumulativeStatFunction because it can
      ' accumulate "partial" results. For instance, results of sub-group. This allows
      ' for better performance.
      Public Class CountIfFunction
        Inherits CumulativeStatFunction
        ' A parameterless constructor is necessary to use the class in XAML.
        Public Sub New()
          MyBase.New()
          m_conditions = New ObservableCollection(Of String)()
          AddHandler m_conditions.CollectionChanged, AddressOf m_conditions_CollectionChanged
        End Sub
        ' Initialize a new instance of the CountIfFunction specifying the ResultPropertyName
        ' and the SourcePropertyName.
        Public Sub New(ByVal resultPropertyName As String, ByVal sourcePropertyNames As String)
          MyBase.New(resultPropertyName, sourcePropertyNames)
          m_conditions = New ObservableCollection(Of String)()
          AddHandler m_conditions.CollectionChanged, AddressOf m_conditions_CollectionChanged
        End Sub
        ' Each condition applies to the values of the corresponding source property name
        ' (e.g., the first condition applies to the values of the first source property name).
        ' Gets the conditions that will be applied to the various values.
        Public ReadOnly Property Conditions() As ObservableCollection(Of String)
          Get
            Return m_conditions
          End Get
        End Property
        ' When the grid needs to create temporary CountIfFunction instances for its
        ' calculation, this method will be called. Be sure to initialize everything
        ' having an impact on the result here.
        Protected Overrides Sub InitializeFromInstance(ByVal source As StatFunction)
          MyBase.InitializeFromInstance(source)
          For Each condition As String In (CType(source, CountIfFunction)).Conditions
            Me.Conditions.Add(condition)
          Next condition
        End Sub
        ' Validate the CountIf statistical function to make sure that it is capable
        ' to calculate its result. In our case, we need to make sure that a ResultPropertyName
        ' has been specified and that we have the same number of source property names
        ' as conditions.
        Protected Overrides Sub Validate()
          If (Me.ResultPropertyName Is Nothing) OrElse
             (Me.ResultPropertyName = String.Empty) OrElse
             (m_conditions.Count <> Me.SourcePropertyName.Split(","c).Length) Then
            Throw New InvalidOperationException()
          End If
        End Sub
        ' This method will be called when a new calculation is about to begin.
        Protected Overrides Sub Reset()
          m_count = 0
        End Sub
        ' This method will be called for each data item that is part of the set (a group or
        ' the grid).
        Protected Overrides Sub Accumulate(ByVal values As Object())
          Dim i As Integer = 0
          Do While i < m_conditions.Count
            ' As soon as one condition does not match is associated value, we simply
            ' return without having done the accumulation (the count increment).
            If (Not Regex.IsMatch(values(i).ToString(), m_conditions(i))) Then
              Return
            End If
            i += 1
          Loop
          ' The compilation configuration will cause this line to throw
          ' if an OverflowException occurs.
          m_count += 1
        End Sub
        ' This method will be called when calculating the result of a group having
        ' sub-groups. Obviously, it will be called once for each sub-group.
        Protected Overrides Sub AccumulateChildResult(ByVal childResult As StatResult)
          m_count += Convert.ToInt64(childResult.Value)
        End Sub
        ' This method should return the result calculated so far.
        Protected Overrides Function GetResult() As StatResult
          Return New StatResult(m_count)
        End Function
        ' The addition of the Conditions property, which influences the result of the
        ' statistical function, the CountIf function requires us to override IsEquivalent
        ' and GetEquivalenceKey to return a new key when 2 instances are compared.
        Protected Overrides Function IsEquivalent(ByVal statFunction As StatFunction) As Boolean
          Dim countIfFunction As CountIfFunction = TryCast(statFunction, CountIfFunction)
          If countIfFunction Is Nothing Then
            Return False
          End If
          If m_conditions.Count <> countIfFunction.Conditions.Count Then
            Return False
          End If
          Dim i As Integer = 0
          Do While i < m_conditions.Count
            If m_conditions(i) <> countIfFunction.Conditions(i) Then
              Return False
            End If
            i += 1
          Loop
          Return MyBase.IsEquivalent(statFunction)
        End Function
        Protected Overrides Function GetEquivalenceKey() As Integer
          Dim hashCode As Integer = MyBase.GetEquivalenceKey()
          Dim i As Integer = 0
          Do While i < m_conditions.Count
            hashCode = hashCode Xor m_conditions(i).GetHashCode()
            i += 1
          Loop
          Return hashCode
        End Function
        ' Do not allow the Conditions property to be changed if the statistical function has
        ' been sealed (i.e, assigned to the DataGridCollectionView.StatFunctions property).
        Private Sub m_conditions_CollectionChanged(ByVal sender As Object, ByVal e As NotifyCollectionChangedEventArgs)
          Me.CheckSealed()
        End Sub
        Private m_conditions As ObservableCollection(Of String)
        Private m_count As Long
      End Class
    End Namespace
    C#
    Copy Code
    using System;
    using Xceed.Wpf.DataGrid.Stats;
    using System.Text.RegularExpressions;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    namespace Xceed.Wpf.Documentation
    {
     // This statistical function derives from CumulativeStatFunction because it can
     // accumulate "partial" results. For instance, results of sub-group. This allows
     // for better performance.
     public class CountIfFunction : CumulativeStatFunction
     {
       // A parameterless constructor is necessary to use the class in XAML.
       public CountIfFunction()
         : base()
       {
         m_conditions = new ObservableCollection<string>();
         m_conditions.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( m_conditions_CollectionChanged );
       }
       // Initialize a new instance of the CountIfFunction specifying the ResultPropertyName
       // and the SourcePropertyName.
       public CountIfFunction( string resultPropertyName, string sourcePropertyNames )
         : base( resultPropertyName, sourcePropertyNames )
       {
         m_conditions = new ObservableCollection<string>();
         m_conditions.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( m_conditions_CollectionChanged );
       }
       // Each condition applies to the values of the corresponding source property name
       // (e.g., the first condition applies to the values of the first source property name).
       // Gets the conditions that will be applied to the various values.
       public ObservableCollection<string> Conditions
       {
         get
         {
           return m_conditions;
         }
       }
       // When the grid needs to create temporary CountIfFunction instances for its
       // calculation, this method will be called. Be sure to initialize everything
       // having an impact on the result here.
       protected override void InitializeFromInstance( StatFunction source )
       {
         base.InitializeFromInstance( source );
         foreach( string condition in ( ( CountIfFunction )source ).Conditions )
           this.Conditions.Add( condition );
       }
       // Validate the CountIf statistical function to make sure that it is capable
       // to calculate its result. In our case, we need to make sure that a ResultPropertyName
       // has been specified and that we have the same number of source property names
       // as conditions.
       protected override void Validate()
       {
         if( ( string.IsNullOrEmpty( ResultPropertyName ) ) ||
             ( m_conditions.Count != this.SourcePropertyName.Split( ',' ).Length ) )
         {
           throw new InvalidOperationException();
         }
       }
       // This method will be called when a new calculation is about to begin.
       protected override void Reset()
       {
         m_count = 0;
       }
       // This method will be called for each data item that is part of the set (a group or
       // the grid).
       protected override void Accumulate( object[] values )
       {
         for( int i = 0; i < m_conditions.Count; i++ )
         {
           // As soon as one condition does not match is associated value, we simply
           // return without having done the accumulation (the count increment).
           if( !Regex.IsMatch( values[ i ].ToString(), m_conditions[ i ] ) )
             return;
         }
         // In case of an overflow, we want to stop the calculation and report the error.
         checked
         {
           m_count++;
         }
       }
       // This method will be called when calculating the result of a group having
       // sub-groups. Obviously, it will be called once for each sub-group.
       protected override void AccumulateChildResult( StatResult childResult )
       {
         checked
         {
           m_count += Convert.ToInt64( childResult.Value );
         }
       }
       // This method should return the result calculated so far.
       protected override StatResult GetResult()
       {
         return new StatResult( m_count );
       }
       // The addition of the Conditions property, which influences the result of the
       // statistical function, the CountIf function requires us to override IsEquivalent
       // and GetEquivalenceKey to return a new key when 2 instances are compared.
       protected override bool IsEquivalent( StatFunction statFunction )
       {
         CountIfFunction countIfFunction = statFunction as CountIfFunction;
         if( countIfFunction == null )
           return false;
         if( m_conditions.Count != countIfFunction.Conditions.Count )
           return false;
         for( int i = 0; i < m_conditions.Count; i++ )
         {
           if( m_conditions[ i ] != countIfFunction.Conditions[ i ] )
             return false;
         }
         return base.IsEquivalent( statFunction );
       }
       protected override int GetEquivalenceKey()
       {
         int hashCode = base.GetEquivalenceKey();
         for( int i = 0; i < m_conditions.Count; i++ )
           hashCode ^= m_conditions[ i ].GetHashCode();
         return hashCode;
       }
       // Do not allow the Conditions property to be changed if the statistical function has
       // been sealed (i.e., assigned to the DataGridCollectionView.StatFunctions property).
       private void m_conditions_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
       {
         this.CheckSealed();
       }
       private ObservableCollection<string> m_conditions;
       private long m_count;
     }
    }